package com.jquest.data;

import com.jquest.layer.MapLayer;
import com.jquest.layer.TileLayer;
import com.jquest.layer.SpriteLayer;
import com.jquest.io.TilesetLoader;
import com.jquest.misc.Tileset;

import java.util.ArrayList;
import java.io.*;

import org.newdawn.slick.Graphics;

/**
 * Created by IntelliJ IDEA.
 * User: Johan
 * Date: 2009-dec-11
 * Time: 03:28:25
 * To change this template use File | Settings | File Templates.
 */
public class Map {
    private ArrayList<MapLayer> layers;

    private int height, width;


    public Map() {
        layers = new ArrayList<MapLayer>();
    }

    public Map(int width, int height) {
        layers = new ArrayList<MapLayer>();
        this.width = width;
        this.height = height;
    }

    public int getHeight() {
        return height;
    }
    
    public int getWidth() {
        return width;
    }

    public int getCanvasHeight() {
        return height * Tile.TILE_HEIGHT;
    }

    public int getCanvasWidth() {
        return width * Tile.TILE_WIDTH;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public static Map fromFile(String file) throws IOException {
        Map map = new Map();
        DataInputStream dis = new DataInputStream(new FileInputStream(new File(file)));
        TilesetLoader tsl = new TilesetLoader();

        if(dis.readInt() != 0xABC) {
            throw new IOException("Invalid map-file format!");
        }
        int mapWidth = dis.readInt();
        int mapHeight = dis.readInt();
        map.setHeight(mapHeight);
        map.setWidth(mapWidth);

        int layerCount = dis.readInt();
        for(int i = 0; i < layerCount; i++) {
            int layerType = dis.readByte();
            if(layerType == 0) {
                String tileset = dis.readUTF();
                Tileset t;
                try {
                    t = tsl.load(tileset);
                } catch(Exception e) {
                    System.out.println("ERROR! Tileset "+tileset+" not found!");
                    return null;
                }
                TileLayer layer = new TileLayer(map, t);
                for(int x = 0; x < layer.getTiles().length; x++) {
                    for(int y = 0; y < layer.getTiles()[x].length; y++) {
                        int imageIndex = dis.readInt();
                        int tileX = dis.readInt();
                        int tileY = dis.readInt();
                        layer.set(x, y, new Tile(tileX, tileY, imageIndex));
                    }
                }
                map.addLayer(layer);
            } else if(layerType == 1) {
                String layerName = dis.readUTF();
                int spriteCount = dis.readInt();
                SpriteLayer layer = new SpriteLayer(layerName);
                for(int j = 0; j < spriteCount; j++) {
                    int spriteIdx = dis.readInt();
                    int spriteX = dis.readInt();
                    int spriteY = dis.readInt();
                    layer.add(new Sprite(spriteX, spriteY, spriteIdx));
                }
                map.addLayer(layer);
            }        
        }
        dis.close();
        return map;
    }

    public void save(String file) throws IOException {
        DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File(file)));
        dos.writeInt(0xABC);
        dos.writeInt(getWidth());
        dos.writeInt(getHeight());

        dos.writeInt(layers.size());
        for(int i = 0; i < layers.size(); i++) {
            if(layers.get(0) instanceof TileLayer) {
                TileLayer tileLayer = (TileLayer) layers.get(0);
                dos.writeByte(0);
                dos.writeUTF(tileLayer.getTileset().getFileName());
                for(int x = 0; x < tileLayer.getTiles().length; x++) {
                    for(int y = 0; y < tileLayer.getTiles()[x].length; y++) {
                        dos.writeInt(tileLayer.getTiles()[x][y].getImageIndex());
                        dos.writeInt(x);
                        dos.writeInt(y);
                    }
                }
            } else {
                SpriteLayer spriteLayer = (SpriteLayer) layers.get(0);
                dos.writeByte(1);
                dos.writeUTF(spriteLayer.getName());
                dos.writeInt(spriteLayer.getCount());
                for(int j = 0; j < spriteLayer.getCount(); j++) {
                    Sprite sprite = spriteLayer.getSprites().get(0);
                    dos.writeInt(sprite.getSpriteIndex());
                    dos.writeInt(sprite.getX());
                    dos.writeInt(sprite.getY());
                }
            }
        }
        dos.close();
    }

    public MapLayer getLayer(int index) {
        return layers.get(index);
    }

    public void addLayer(MapLayer layer) {
        layers.add(layer);
    }

    public void disableLayer(int index) {
        layers.get(index).setEnabled(false);
    }

    public void enableLayer(int index) {
        layers.get(index).setEnabled(true);
    }

    public void update(int time) {
        for(MapLayer layer : layers) {
            layer.update(time);
        }
    }

    public void render(Graphics g) {
        for(MapLayer layer : layers) {
            layer.render(g);
        }
    }

}
